﻿import cgi
import datetime
import os
import re
import sys
import urllib
import urlparse
import wsgiref.handlers
import logging

from google.appengine.api import datastore
from google.appengine.api import datastore_types
from google.appengine.api import users
from google.appengine.ext import webapp
from google.appengine.ext import db
from google.appengine.ext.webapp import template
from google.appengine.api import memcache

from django.utils import simplejson

from model import * 

# Set to true if we want to have our webapp print stack traces, etc
_DEBUG = True
##HOMEMEMOK = True
##ENTRYMEMOK = True
##TAGMEMOK = True
##CATMEMOK =True
TOOMANYPPL='TOO MANY PEOPLE NOW,Please Try Again Later'
COMMENTS_LIST_NUM = 15
ENTRIES_PER_PAGE=20
POP_ENTRIES_NUM=10
ERROR='This page may be moved or deleted'
NOENTRYINCAT = 'There is no entry in this category now'

class BaseRequestHandler(webapp.RequestHandler):
  """Supplies a common template generation function.

  When you call generate(), we augment the template variables supplied with
  the current user in the 'user' variable and the current webapp request
  in the 'request' variable.
    """ 
##  def generate(self, template_name, template_values={}):
##     self.response.out.write(self.pregenerate(template_name, template_values))

  def generate(self, template_name, template_values={}):
    values = {
      'request': self.request,
      'application_name': 'DocFansOrg',
      'allcats':Category.all().order('name'),
      'alltags':Tag.all().order('name'),
      'is_entrypage':False,
      'pop_entries':Entry.all().order('-accesscount').fetch(POP_ENTRIES_NUM),
      'focus_entry':Entry.all().order('-accesscount').get(),
      'hot_entries':Entry.all().order('-accesscount').fetch(4,1),
      'latest_comments':Comment.all().order('-pub_date').fetch(10),
      'total':Entry.all().count(),
      'is_admin':users.is_current_user_admin(),
      'logout_url':users.create_logout_url(self.request.uri)
        }
    values.update(template_values)
    directory = os.path.dirname(__file__)
    path = os.path.join(directory, os.path.join('templates', template_name))
    self.response.out.write(template.render(path, values, debug=_DEBUG))

class HomePage(BaseRequestHandler):
    def get(self, page=1):
        try:
##        global HOMEMEMOK
            if page:
              page=int(page)
            else:
              page=1
            offset = (page-1) * ENTRIES_PER_PAGE
            count = Entry.all().count()
            if offset >= count:
                self.generate('oops.html',{'error':ERROR})
                return
    ##        if HOMEMEMOK and not users.is_current_user_admin():
    ##            memresult=memcache.get(key=str(page), namespace="HomePage")
    ##            if memresult is not None:
    ##                self.response.out.write(memresult)
    ##                logging.info("Homepage Memcached Get!")
    ##                return
            lastpage = int(count/ENTRIES_PER_PAGE)
            if lastpage*ENTRIES_PER_PAGE < count:
              lastpage = lastpage +1
            if lastpage >11:
              pages = range(1,10)
              dotdotdot = True
            else:
              pages = range(1, lastpage)
              dotdotdot = False
            if page == 1:
              haspre = False
            else:
              haspre = True
            if offset + ENTRIES_PER_PAGE < count:
              hasnext = True
            else:
              hasnext = False
            entries = Entry.all().order('-pub_date').fetch(ENTRIES_PER_PAGE, offset)
            self.generate('HomePage.html',{'entries':entries, 'prenav':"", \
                                         'currentpage':page, 'pages':pages, 'dotdotdot':dotdotdot, 'lastpage':lastpage, \
                                           'prepage':page-1, 'nextpage':page+1, 'haspre':haspre, 'hasnext':hasnext})
        except:
            self.response.clear()
            self.generate('oops.html',{'error':TOOMANYPPL})
##        self.response.out.write(data)
##        if not users.is_current_user_admin():
##            if memcache.set(key=str(page), value=data, time=3600*24*20, namespace="HomePage"):
##                HOMEMEMOK =True
##                logging.info("Homepage Memcached Set!")
##            else:
##                logging.error("Homepage Memcache set failed.")

class EntryPage(BaseRequestHandler):
  def get(self, id = None):
##    global ENTRYMEMOK
    try:
        if id:
            entry = Entry.get_by_id(int(id))
            if entry == None:
                self.generate('oops.html',{'error':ERROR})
                return
            entry.accesscount=entry.accesscount + 1
            entry.put()
    ##        if ENTRYMEMOK and not users.is_current_user_admin():
    ##            memresult=memcache.get(key=str(id), namespace="EntryPage")
    ##            if memresult is not None:
    ##                self.response.out.write(memresult)
    ##                logging.info("Entrypage Memcached Get!")
    ##                return
            relatedentries=entry.category.entry_set.fetch(POP_ENTRIES_NUM)
            #pub_date_str= entry.pub_date.strftime("%Y-%m-%d %H:%M:%S")
            self.generate('EntryPage.html',{'entry':entry, 'is_entrypage':True, 'relatedentries':relatedentries})
    ##        self.response.out.write(data)
    ##        if not users.is_current_user_admin():
    ##            if memcache.set(key=str(id), value=data, time=3600*24*20, namespace="EntryPage"):
    ##                ENTRYMEMOK =True
    ##                logging.info("Entrypage Memcached Set!")
    ##            else:
    ##                logging.error("Entrypage Memcache set failed.")
        else:
            self.generate('oops.html',{'error':ERROR})
    except:
        self.response.clear()
        self.generate('oops.html',{'error':TOOMANYPPL})
    
class TagPage(BaseRequestHandler):
  """
    Show all of the entries belonging to one Tag
  """
  def get(self, id, page=1):
##    global TAGMEMOK
    try:
        page=int(page)
        if page >= 1:
          tag = Tag.get_by_id(int(id))
          if tag == None:
                self.generate('oops.html',{'error':ERROR})
                return
        entriescount = tag.entriescount()
        offset = (page-1) * ENTRIES_PER_PAGE
        if offset >= entriescount:
            self.generate('oops.html',{'error':ERROR})
            return 
    ##    if TAGMEMOK and not users.is_current_user_admin():
    ##        memresult=memcache.get(key=str(page), namespace="TagPage"+str(id))
    ##        if memresult is not None:
    ##            self.response.out.write(memresult)
    ##            logging.info("Tagpage Memcached Get!")
    ##            return
        lastpage = int(entriescount/ENTRIES_PER_PAGE)
        if lastpage*ENTRIES_PER_PAGE < entriescount:
            lastpage = lastpage +1
        if lastpage >11:
            pages = range(1,10)
            dotdotdot = True
        else:
            pages = range(1, lastpage)
            dotdotdot = False
        if page == 1:
            haspre = False
        else:
            haspre = True
        if offset + ENTRIES_PER_PAGE < entriescount:
            hasnext = True
        else:
            hasnext = False
        entrytags=Tag.get_by_id(int(id)).entrytag_set.order('-pub_date').fetch(ENTRIES_PER_PAGE, offset)
        entries=(x.entry for x in entrytags)
        prenav ='/tag/' + str(id)
        #self.generate('TagPage2.html',{'entrytags':entrytags, 'entriescount':entriescount,'tag':tag, 'prepage':page-1, 'nextpage':page+1, 'haspre':haspre, 'hasnext':hasnext })
        #self.generate('CatPage.html',{'entries':entries, 'entriescount':entriescount,'tag':tag, 'prepage':page-1, 'nextpage':page+1, 'haspre':haspre, 'hasnext':hasnext })
        self.generate('CatPage.html',{'entries':entries, 'prenav':prenav, 'tag':tag, \
                                      'entriescount':entriescount, 'currentpage':page, 'pages':pages, 'dotdotdot':dotdotdot, 'lastpage':lastpage, 'prepage':page-1, \
                                      'nextpage':page+1, 'haspre':haspre, 'hasnext':hasnext})
    except:
        self.response.clear()
        self.generate('oops.html',{'error':TOOMANYPPL})
##    self.response.out.write(data)
##    if not users.is_current_user_admin():
##        if memcache.set(key=str(page), value=data, time=3600*24*20, namespace="TagPage"+str(id)) and not users.is_current_user_admin():
##            logging.info("Tagpage Memcached Set!")
##            TAGMEMOK =True
##        else:
##            logging.error("Tagpage Memcache set failed.")

class CategoryPage(BaseRequestHandler):
  """
    Show all of the entries belonging to one Category
  """
  def get(self, id, page=1):
##    global CATMEMOK
    try:
        page = int(page)
        if page >= 1:
            cat = Category.get_by_id(int(id))
            if cat == None:
                self.generate('oops.html',{'error':ERROR})
                return
        entriescount = cat.entriescount()
        offset = (page-1) * ENTRIES_PER_PAGE
        if offset >= entriescount:
            self.generate('oops.html',{'error':ERROR})
            return 
    ##    if CATMEMOK and not users.is_current_user_admin():
    ##        memresult=memcache.get(key=str(page), namespace="CategoryPage"+str(id))
    ##        if memresult is not None:
    ##            self.response.out.write(memresult)
    ##            logging.info("CategoryPage Memcached Get!")
    ##            return
        lastpage = int(entriescount/ENTRIES_PER_PAGE)
        if lastpage*ENTRIES_PER_PAGE < entriescount:
            lastpage = lastpage +1
        if lastpage >11:
            pages = range(1,10)
            dotdotdot = True
        else:
            pages = range(1, lastpage)
            dotdotdot = False
        if page == 1:
            haspre = False
        else:
            haspre = True
        if offset + ENTRIES_PER_PAGE < entriescount:
            hasnext = True
        else:
            hasnext = False
        entries = Category.get_by_id(int(id)).entries().order('-pub_date').fetch(ENTRIES_PER_PAGE, offset)
        prenav ='/cat/' + str(id)
        #self.generate('CatPage.html',{'entries':entries, 'entriescount':entriescount, 'category':cat, 'prepage':page-1, 'nextpage':page+1, 'haspre':haspre, 'hasnext':hasnext})
        self.generate('CatPage.html',{'entries':entries, 'prenav':prenav, 'category':cat, \
                                      'entriescount':entriescount, 'currentpage':page, 'pages':pages, \
                                              'dotdotdot':dotdotdot, 'lastpage':lastpage, 'prepage':page-1, \
                                              'nextpage':page+1, 'haspre':haspre, 'hasnext':hasnext})
    except:
        self.response.clear()
        self.generate('oops.html',{'error':TOOMANYPPL})
##    self.response.out.write(data)
##    if not users.is_current_user_admin():
##        if memcache.set(key=str(page), value=data, time=3600*24*20, namespace="Categorypage"+str(id)) and not users.is_current_user_admin():
##            CATMEMOK =True
##            logging.info("CategoryPage Memcached Set!")
##        else:
##            logging.error("Categorypage Memcache set failed.")

class SearchPage(BaseRequestHandler):
    def get(self):
        self.generate('SearchPage.html',{'is_entrypage':True, 'search_content':''})
    def post(self):
        search_content = self.request.get('word')
        self.generate('SearchPage.html',{'is_entrypage':True, 'search_content':search_content})

class PostComment(BaseRequestHandler):
    def get(self, id=None):
        if id:
            self.redirect('/entry/'+str(id)+'/')
        else:
            self.generate('oops.html',{'error':ERROR})
    def post(self, id=None):
##        global HOMEMEMOK
##        global ENTRYMEMOK
##        global TAGMEMOK
##        global CATMEMOK
        """
        Save the comment attactched to this post
        """
        try:
            entry = Entry.get_by_id(int(id))
            name = cgi.escape(self.request.get('user_name'))
            email = cgi.escape(self.request.get('user_email'))
            content = cgi.escape(self.request.get('content'))

            if not name:
                name = "Anonymous"
            if not email:
                email = "None"
            if content:
                comment = Comment( user_name = name, user_mail = email, content = content, entry = entry)
                comment.put()
            #self.generate('CommentPage.html',{'id':id, 'entry':entry})
            #url='/entry/'+ str(entry.id) + '/' + entry.titleurl
            directory = os.path.dirname(__file__)
            path = os.path.join(directory, os.path.join('templates', 'Comments.html'))
            comment_c = template.render(path,{'entry':entry}, debug=_DEBUG)
            self.response.out.write(simplejson.dumps((True,comment_c.decode('utf8'))))
        except:
            self.response.clear()
            self.generate('oops.html',{'error':TOOMANYPPL})
##        HOMEMEMOK = False
##        ENTRYMEMOK = False
##        TAGMEMOK = False
##        CATMEMOK = False
        #self.response.out.write((True,comment_c.decode('utf8')))
        #self.redirect('/')

# Enter Zone of Admin
# Enter Zone of Admin
# Enter Zone of Admin
class Visame(BaseRequestHandler):
    def get(self):
        self.redirect('/')

class PublishEntry(BaseRequestHandler):
  def get(self):
    self.generate('publish.html')
    
  def post(self):
##    global HOMEMEMOK
##    global ENTRYMEMOK
##    global TAGMEMOK
##    global CATMEMOK
    """
    Save post, tags and category
    """
    title = cgi.escape(self.request.get('title'))
    #titleurl = UrlPro(title)
    excerpt = self.request.get('excerpt')
    content = self.request.get('content')
    cat = cgi.escape(self.request.get('category'))
    imgname = cgi.escape(self.request.get('imgname'))
    query = Category.all().filter("name =",cat).fetch(1)
    if not query or len(query) == 0:
        cate = Category(name = cat, imgname = imgname)
        cate.put()
    else:
        cate=query[0]
    entry = Entry(title = title, excerpt = excerpt, content = content, category = cate)
    entry.put()
    tags = cgi.escape(self.request.get('tags')).split()
    for each in tags:
        #check whether we have saved this tag or not
        query = Tag.all().filter("name =",each).fetch(1)
        if len(query)==0:
            tag = Tag(name = each)
            tag.put()
        else:
            tag=query[0]
        #save postcategory
        entrytag = EntryTag(entry = entry, tag = tag, pub_date = entry.pub_date)
        entrytag.put()
##    HOMEMEMOK = False
##    ENTRYMEMOK = False
##    TAGMEMOK = False
##    CATMEMOK = False
    self.redirect('/')

class EditEntry(BaseRequestHandler):
  def get(self,id):
    entry = Entry.get_by_id(int(id))
    entry_tags =""
    for tag in entry.tags():
        entry_tags = entry_tags + " "+tag.name
    entry_tags = entry_tags[1:]
    self.generate('publish.html', {'entry':entry,
                                   'entry_tags':entry_tags,
                                   })
  def post(self,id):
##    global HOMEMEMOK
##    global ENTRYMEMOK
##    global TAGMEMOK
##    global CATMEMOK

    #update the post
    entry = Entry.get_by_id(int(id))
    #entry.category.entry_set.filter("pub_date = ",entry.pub_date).get().delete()
    #entry.category.entry_set.filter("id = ",entry.id).get().delete()
    #EntryTag.all().filter("entry =", entry)
    db.delete(entry.entrytag_set)

    entry.title = cgi.escape(self.request.get('title'))
    #entry.titleurl = UrlPro(entry.title)
    entry.excerpt = self.request.get('excerpt')
    entry.content = self.request.get('content')
    cat = cgi.escape(self.request.get('category'))
    imgname = cgi.escape(self.request.get('imgname'))
    query = Category.all().filter("name =",cat).fetch(1)
    if not query or len(query) == 0:
        cate = Category(name = cat, imgname = imgname)
        cate.put()
    else:
        cate=query[0]
    entry.category = cate
    entry.put()
    tags = cgi.escape(self.request.get('tags')).split()
    for each in tags:
        #check whether we have saved this tag or not
        query = Tag.gql("WHERE name = :1", each)
        tag = query.get()
        if None == tag:
            # this is a new tag
            tag = Tag(name = each)
            tag.put()
            #save postcategory
        entrytag = EntryTag(entry = entry, tag = tag, pub_date = entry.pub_date)
        entrytag.put()
##    HOMEMEMOK = False
##    ENTRYMEMOK = False
##    TAGMEMOK = False
##    CATMEMOK = False
    direct = '/entry/'+str(entry.id)+'/'
    self.redirect(direct)

class PreDeleteEntry(BaseRequestHandler):
    def get(self, id):
      self.generate('PreDelete.html',{'deleteid':str(id)})
    def post(self, id):
        answer = cgi.escape(self.request.get('answer'))
        id = cgi.escape(self.request.get('id'))
        if answer=='YES':
            self.redirect('/Visame/delete/'+str(id)+'/')
        else:
            self.redirect('/')

class DeleteEntry(BaseRequestHandler):
  def get(self, id):
##    global HOMEMEMOK
##    global ENTRYMEMOK
##    global TAGMEMOK
##    global CATMEMOK

    entry = Entry.get_by_id(int(id))
    #for comment in entry.comment_set:
    #    comment.delete()
    db.delete(entry.comment_set)
    db.delete(entry.entrytag_set)
    #entry.category.entry_set.filter("title =",entry.title).get().delete()
    #entry.category.entry_set.filter("pub_date = ",entry.pub_date).get().delete()
    entry.delete()
##    HOMEMEMOK = False
##    ENTRYMEMOK = False
##    TAGMEMOK = False
##    CATMEMOK = False
    self.redirect('/')

class DeleteComment(BaseRequestHandler):
  def get(self, id):
##    global HOMEMEMOK
##    global ENTRYMEMOK
##    global TAGMEMOK
##    global CATMEMOK

    comment = Comment.get_by_id(int(id))
    comment.delete()
    try:
        self.referer = self.request.headers['referer']
    except:
        self.referer = '/'
##    HOMEMEMOK = False
##    ENTRYMEMOK = False
##    TAGMEMOK = False
##    CATMEMOK = False
    self.redirect(self.referer)

##class UpdateMemcache(BaseRequestHandler):
##    def get(self):
##        global HOMEMEMOK
##        global ENTRYMEMOK
##        global TAGMEMOK
##        global CATMEMOK
##        
##        HOMEMEMOK = False
##        ENTRYMEMOK = False
##        TAGMEMOK = False
##        CATMEMOK = False
##        self.redirect('/')
        
class ErrorPage(BaseRequestHandler):
    def get(self, slug=None):
        self.generate('oops.html',{'error':ERROR})
        
def main():
    application = webapp.WSGIApplication([
    ('/', HomePage),
    ('/entry/([0-9]+)/', EntryPage),
    ('/cat/([0-9]+)/([0-9]+)/', CategoryPage),
    ('/tag/([0-9]+)/([0-9]+)/', TagPage),
    ('/search/',SearchPage),
    ('/PostComment/([0-9]+)/', PostComment),
##    ('/Visame/updatememcache/', UpdateMemcache),
    ('/Visame/publish/', PublishEntry),
    ('/Visame/edit/([0-9]+)/', EditEntry),
    ('/Visame/predelete/([0-9]+)/', PreDeleteEntry),
    ('/Visame/delete/([0-9]+)/', DeleteEntry),
    ('/Visame/delcomment/([0-9]+)/', DeleteComment),
    ('/Visame/',Visame),
    ('/([0-9]+)/', HomePage),
    ('/(.*)', ErrorPage),
    ], debug=_DEBUG)
    wsgiref.handlers.CGIHandler().run(application)

if __name__ == '__main__':
  main()